perm filename PUPOP.C[11,HE] blob sn#688204 filedate 1982-12-06 generic text, type T, neo UTF8
/* LINTLIBRARY */
/*
 * pupopen.c
 *
 * pupopen returns an open Pup Channel between two
 * a socket on this host, and a host/net/socket over
 * some network.  It also decides what sort of
 * transport medium to use, and remembers the
 * immediate destination address for transmitting packets
 * to the remote host (e.g., the address of the first
 * gateway.)  If the destination is NULL, then it
 * is ignored.
 *
 * pupsetdest changes the destination port for a channel.
 * Since this also implies re-routing, the bulk of the
 * routing code should go in here; pupopen then just
 * calls this routine.
 *
 * Jeffrey Mogul & Dan Kolkowitz	12-January-1981
 *					25-january-1981
 *	JCM: added routing		21 July 1981
 *
 */

#include <puppacket.h>
#include <pupconstants.h>
#include <pupstatus.h>

pupopen(Pchan,srcsock,Dst)
struct	PupChan	*Pchan;		/* channel data structure */
Socket	srcsock;		/* source socket */
struct	Port	*Dst;		/* destination host/net/socket */
{
	int	sderr;

	Pchan->mystic = PC_MYSTIC;	/* mark channel as initialized */

	/*
	 * If the caller has supplied a destination port,
	 * take care of routing now.
	 */
	
	if (Dst != NULL) {
		sderr = pupsetdest(Pchan,Dst);
		if (sderr != OK)	/* probably: NOROUTE */
			return(sderr);
		}
	
	/*
	 * Here we would deal with special cases according
	 * to transport type if there were more than one.
	 */

	/* FOLLOWING IS UNIX SPECIFIC (ifid and ofid get same fid) !!! */
	if ( (Pchan->ifid = enopen()) < 0 )
		return(NOCHAN);
	else {	/* positive fid means it worked */
		Pchan->ofid = Pchan->ifid;	/* For Unix, file ids are r/w */
		Pchan->SrcPort.host = pupgethost(Pchan);
		Pchan->SrcPort.net = getnet(Pchan->ifid);
		Pchan->SrcPort.socket = srcsock;

		Pchan->mode = 0;
		
#ifdef	VAX
		Pchan->TimeoutSet = 0;	/* remember that no timeout is set */
#endif	VAX

		return(OK);
		}
}

pupsetdest(Pchan, DstPort)
struct	PupChan *Pchan;		/* channel to set destination on */
struct	Port	*DstPort;	/* new destination */
{
	Host	via;		/* host address for first hop */

	/*
	 * First thing to do is to chose routing.
	 * If the network specified is zero, then we should NOT
	 * attempt to determine a route, but should instead
	 * assume a direct connection to our local net.  This
	 * is necessary because pupopen() is called recursively
	 * with such an address in the event that a routing table
	 * does not exist already.
	 */
	if (DstPort->net) {	/* Ok, find a route */
		if (puproute(DstPort,&via,NULL) != OK)
			return(NOROUTE);
	}
	else	/* use direct routing */
		via = DstPort->host;

	Pchan->transport = ETHERNET;

	Pchan->ImmNet = 0;		/* this should be better! */
	Pchan->ImmHost = via;

	Pchan->DstPort.host = DstPort->host;
	Pchan->DstPort.net = DstPort->net;
	Pchan->DstPort.socket = DstPort->socket;

	Pchan->SrcPort.net = getnet(Pchan->ifid);
		/* this may not have been right before */
	return(OK);
}